ASP.NET MVC 利用ActionFilterAttribute实现统一权限控制

您所在的位置:网站首页 net core 权限框架 ASP.NET MVC 利用ActionFilterAttribute实现统一权限控制

ASP.NET MVC 利用ActionFilterAttribute实现统一权限控制

2023-07-17 11:31| 来源: 网络整理| 查看: 265

环境:ASP.NET MVC

本文介绍在asp.net mvc框架下,基于AOP指导思想进行的权限控制实操。

在开始前,需要了解一下ActionFilterAttribute,他下面有4个关于Action执行过程的几个方法,本文主要用到的是OnActionExecuting()。

ActionFilterAttribute:表示筛选器特性的基类。

ActionFilterAttribute.OnActionExecuting():在执行操作方法之前由 ASP.NET MVC 框架调用。

namespace System.Web.Mvc { // // 摘要: // 表示筛选器特性的基类。 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)] public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter { // // 摘要: // 初始化 System.Web.Mvc.ActionFilterAttribute 类的新实例。 protected ActionFilterAttribute(); // // 摘要: // 在执行操作方法后由 ASP.NET MVC 框架调用。 // // 参数: // filterContext: // 筛选器上下文。 public virtual void OnActionExecuted(ActionExecutedContext filterContext); // // 摘要: // 在执行操作方法之前由 ASP.NET MVC 框架调用。 // // 参数: // filterContext: // 筛选器上下文。 public virtual void OnActionExecuting(ActionExecutingContext filterContext); // // 摘要: // 在执行操作结果后由 ASP.NET MVC 框架调用。 // // 参数: // filterContext: // 筛选器上下文。 public virtual void OnResultExecuted(ResultExecutedContext filterContext); // // 摘要: // 在执行操作结果之前由 ASP.NET MVC 框架调用。 // // 参数: // filterContext: // 筛选器上下文。 public virtual void OnResultExecuting(ResultExecutingContext filterContext); } }

 下面是具体操作步骤:

1、在Web项目下面建一个Filters文件夹,添加一个类SkipLogin,继承Attribute,主要用来跳过登录验证。

using System; namespace Test.Web.Filters { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class SkipLogin : Attribute { } }

2、在Filters文件夹,添加一个类SkipVerification,继承Attribute,主要用来跳过Action访问权限验证。

using System; namespace Test.Web.Filters { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class SkipVerification : Attribute { } }

3、在Filters文件夹,添加一个类PermissionValidation,继承ActionFilterAttribute,重写ActionFilterAttribute的OnActionExecuting。

4、在检查用户权限之前,要判断是否有跳过权限验证的标记(SkipLogin 和 SkipVerification)。

    A、登录权限验证,Ajax和非Ajax分开处理,Ajax请求的返回报错信息,非Ajax 如果开启了【Windows身份验证登录】,自动登录,记录日志,没有开启就跳到登录页。

    B、访问权限验证,根据用户角色配置的Action访问权限列表,判断用户是否有当前Action的访问权限。

using Newtonsoft.Json.Linq; using System; using System.Linq; using System.Net; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace Test.Web.Filters { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)] public class PermissionValidation : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { CheckUserPermission(filterContext); } private void CheckUserPermission(ActionExecutingContext filterContext) { //例外情况(不验证登录) var skipLogins = filterContext.ActionDescriptor.GetCustomAttributes(typeof(SkipLogin), true); if (skipLogins == null || skipLogins.Length == 0) { //验证登录 var user = filterContext.HttpContext.Session["USER_INFO"]; if (user == null) { //判断是否为ajax请求 if (filterContext.HttpContext.Request.IsAjaxRequest()) { //Ajax 输出错误信息给脚本 filterContext.Result = AjaxError(filterContext); return; } else { //自动用户登录(Windows身份验证登录) string account = HttpContext.Current.User.Identity.Name; //如果没有获得windows标识,请跳到登录页 if (string.IsNullOrWhiteSpace(account)) { filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Home", action = "Login" })); return; } else { account = account.Substring(account.IndexOf("\\") + 1, account.Length - account.IndexOf("\\") - 1); JObject dbUser = UserBLL.GetDefaultUserByAccount(JObject.FromObject(new { Account = account })); if (dbUser == null) { UserBLL.InitUserByNTID(account); dbUser = UserBLL.GetDefaultUserByAccount(JObject.FromObject(new { Account = account })); } Login(dbUser); } } } //例外情况(不验证权限) var skipVerifications = filterContext.ActionDescriptor.GetCustomAttributes(typeof(SkipVerification), true); if (skipVerifications == null || skipVerifications.Length == 0) { //验证权限 CheckPermission(filterContext, JObject.Parse(user + "")); } } base.OnActionExecuting(filterContext); } /// /// Ajaxes the error. /// /// 过滤器上下文 /// 返回json串 protected JsonResult AjaxError(ActionExecutingContext filterContext) { //将响应状态代码设置为500 filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; return new JsonResult { Data = new { Code = 10001, Msg = "" }, ContentEncoding = System.Text.Encoding.UTF8, JsonRequestBehavior = JsonRequestBehavior.DenyGet }; } private void CheckPermission(ActionExecutingContext filterContext, JObject user) { //根据用户ID获取用户权限列表,如果列表为空直接抛异常 var permissions = ModuleBLL.GetPermissionsByUser(user["ID"].ToString()); if (permissions == null || permissions.Count == 0) { throw new Exception("没有权限!"); } //检查用户是否有当前Action的访问权限 string controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName; string action = filterContext.ActionDescriptor.ActionName; var module = permissions.Where(m => m["Controller"].ToString() == controller && m["Action"].ToString() == action).FirstOrDefault(); if (module == null || module.Type == JTokenType.Null) { throw new Exception("没有权限!"); } } private void Login(JObject userInfo) { HttpContext.Current.Session["USER_INFO"] = userInfo.ToString(); try { string title = "Automatic login through permission verification"; var serverVariables = HttpContext.Current.Request.ServerVariables.AllKeys.ToDictionary( k => k, v => HttpContext.Current.Request.ServerVariables[v]); string content = serverVariables.ToJson(); string args = ""; string returns = ""; JObject log = new JObject(); log.Add("Type", 1); log.Add("Content", string.Format("Operation: {0},Server variable: {1}", title, content)); log.Add("Source", "PermissionValidation"); log.Add("Operator", userInfo["Account"]); log.Add("OperationIp", GetIP()); log.Add("OperationDate", DateTime.Now); log.Add("Params", args); log.Add("Returns", returns); SystemBLL.InsertLog(log); } catch (Exception ex) { LogHelper.Error(ex.Message, ex); } } private string GetIP() { string ip = string.Empty; if (!string.IsNullOrEmpty(HttpContext.Current.Request.ServerVariables["HTTP_VIA"])) ip = Convert.ToString(HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]); if (string.IsNullOrEmpty(ip)) ip = Convert.ToString(HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]); return ip; } } }

5、把PermissionValidation加到控制器的基类BaseController上,这样就可以对所有继承BaseController的控制器进行权限验证管理。

using System.Web.Mvc; using Test.Web.Filters; namespace Test.Web.Controllers { [PermissionValidation] public class BaseController : Controller { } }

6、如果需要跳过权限验证,需要在Action前标记SkipLogin 和 SkipVerification。比如登录页,如果别人没登录你就问人要权限,那就没法玩了。

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Test.Web.Filters; namespace Test.Web.Controllers { public class HomeController : BaseController { [SkipLogin] [SkipVerification] public ActionResult Login() { return View(); } public ActionResult Index() { return View(); } public ActionResult About() { ViewBag.Message = "Your application description page."; return View(); } public ActionResult Contact() { ViewBag.Message = "Your contact page."; return View(); } } }

关于用户权限配置管理方面,本文就不详细介绍了,因为一扯上那个,又是一大堆东西了。。。

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3